import requests
import time
import random
import string
import hashlib
import socket
from xml.etree import ElementTree as ET
from common import config

class WeChatMicropay:
    def __init__(self, sale_info):
        self.api_url = "https://api.mch.weixin.qq.com/pay/micropay"
        self.sale_info = sale_info

    def _gen_nonce_str(self, length=32):
        return ''.join(random.choices(string.ascii_letters + string.digits, k=length))

    def _sign(self, data):
        items = sorted(data.items())
        sign_str = '&'.join([f"{k}={v}" for k, v in items]) + f"&key={config.WECHAT_PAY_DATA['api_key']}"
        return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()

    def _dict_to_xml(self, data):
        xml = ["<xml>"]
        for k, v in data.items():
            xml.append(f"<{k}><![CDATA[{v}]]></{k}>")
        xml.append("</xml>")
        return ''.join(xml)

    def _xml_to_dict(self, xml_str):
        root = ET.fromstring(xml_str)
        return {child.tag: child.text for child in root}

    def pay(self, auth_code):
        """auth_code: 用户扫码"""
        data = config.WECHAT_PAY_DATA.copy()
        data.update({
            "device_info": socket.gethostname(),
            "nonce_str": self._gen_nonce_str(),
            "out_trade_no": self.sale_info["code"],
            "total_fee": self.sale_info["total_price"] * 100,
            "spbill_create_ip": socket.gethostbyname(socket.gethostname()),
            "auth_code": auth_code,
            "detail": [{"goods_detail": [
                {
                    "goods_id": product["id"],
                    "goods_name": product["name"],
                    "quantity": product["quantity"],
                    "price": product["price"] * 100
                } for product in self.sale_info["products"]
            ], "receipt_id": self.sale_info["code"]}]
        })
        data["sign"] = self._sign(data)
        xml_data = self._dict_to_xml(data)
        response = requests.post(self.api_url, data=xml_data.encode("utf-8"), timeout=10)
        return self._xml_to_dict(response.text)

class AlipayMicropay:
    def __init__(self, sale_info):
        self.api_url = "https://openapi.alipay.com/gateway.do"
        self.sale_info = sale_info

    def _gen_nonce_str(self, length=32):
        return ''.join(random.choices(string.ascii_letters + string.digits, k=length))

    def _sign(self, data):
        items = sorted(data.items())
        sign_str = '&'.join([f"{k}={v}" for k, v in items]) + f"&key={config.ALIPAY_DATA['api_key']}"
        return hashlib.md5(sign_str.encode('utf-8')).hexdigest().upper()

    def pay(self, auth_code):
        """auth_code: 用户扫码"""
        data = config.ALIPAY_DATA.copy()
        data.update({
            "app_id": config.ALIPAY_DATA["app_id"],
            "method": "alipay.trade.pay",
            "charset": "utf-8",
            "sign_type": "RSA2",
            "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
            "version": "1.0",
            "biz_content": {
                "out_trade_no": self.sale_info["code"],
                "total_amount": str(self.sale_info["total_price"]),
                "subject": self.sale_info["subject"],
                "auth_code": auth_code
            }
        })
        data["sign"] = self._sign(data)
        response = requests.post(self.api_url, json=data, timeout=10)
        return response.json()